package net.sf.nlp.ltag.data;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class ExtractedTree extends LTAGTree
{
	private boolean beginning = false;
	private Map<LTAGNode, List<ExtractedTree>> operatorMap = new HashMap<LTAGNode, List<ExtractedTree>>();
	
	public boolean isBeginning() {
		return beginning;
	}
	public void setBeginning(boolean beginning) {
		this.beginning = beginning;
	}
	public Map<LTAGNode, List<ExtractedTree>> getOperatorMap() {
		return operatorMap;
	}
	
	public void addOperatorMap(LTAGNode node, ExtractedTree etree) 
	{
		List<ExtractedTree> etrees = operatorMap.get(node);
		
		if (etrees == null)
		{
			etrees = new ArrayList<ExtractedTree>();
			operatorMap.put(node, etrees);
		}
		
		etrees.add(etree);
	}

	public void deleteDuplicatedNodes()
	{
		deleteDuplicatedNodes(getRoot());
	}
	
	private void deleteDuplicatedNodes(LTAGNode node)
	{
		if (node.getChildren() == null)
			return;
		
		for (int i = 0; i < node.getChildren().size(); i++)
			deleteDuplicatedNodes(node.getChildren().get(i));
		
		int size = node.getChildren().size();
		Iterator<LTAGNode> it = node.getChildren().iterator();
		
		List<LTAGNode> removedChildren = new ArrayList<LTAGNode>();
		List<Integer> removedIndexs = new ArrayList<Integer>();
		
		while (it.hasNext())
		{
			LTAGNode child = it.next();
			
			if (!node.getNodeText().equals(child.getNodeText()))
				continue;
			
			if (child.getChildren() == null || child.getChildren().size() == 0)
				continue;
			
			if (size != 1 && child.getChildren().size() != 1)
				continue;
			
			removedChildren.add(child);
			removedIndexs.add(node.getChildren().indexOf(child));
			
			mergeOperatorMap(child, node);
			it.remove();
		}
		
		for (int i = 0; i < removedChildren.size(); i++)
		{
			LTAGNode removedChild = removedChildren.get(i);
			int removedIndex = removedIndexs.get(i);
			
			node.getChildren().addAll(removedIndex, removedChild.getChildren());
		}
	}
	
	private void mergeOperatorMap(LTAGNode child, LTAGNode parent)
	{
		List<ExtractedTree> etrees = operatorMap.remove(child);
		if (etrees == null || etrees.size() == 0)
			return;
		
		List<ExtractedTree> parentEtrees = operatorMap.get(parent);
		if (parentEtrees == null)
		{
			parentEtrees = new ArrayList<ExtractedTree>();
			operatorMap.put(parent, parentEtrees);
		}
		
		parentEtrees.addAll(etrees);
	}
	
	public void generateNoAdjunctNode()
	{
		generateNoAdjunctNode(getRoot());
	}
	
	public void generateNoAdjunctNode(LTAGNode node)
	{
		if (node.getChildren() == null || node.getChildren().size() == 0)
			return;
		
		if (operatorMap.containsKey(node))
			return;
		
		operatorMap.put(node, new ArrayList<ExtractedTree>());
		
		for (LTAGNode child : node.getChildren())
			generateNoAdjunctNode(child);
	}
	
	public String toLTAG()
	{
		StringBuffer sb = new StringBuffer();
		
		sb.append(super.toLTAG());
		
		sb.append("{");
		Iterator<LTAGNode> nodes = operatorMap.keySet().iterator();
		
		while (nodes.hasNext())
		{
			LTAGNode node = nodes.next();
			
			sb.append(node.getNodeText()).append("=");
			sb.append(operatorMap.get(node));
		}
		
		sb.append("}");
		
		return sb.toString();
	}
	
	public static ExtractedTree copyFrom(LTAGTree tree)
	{
		ExtractedTree etree = new ExtractedTree();
		
		LTAGTree clone = (LTAGTree)tree.clone();
		
		etree.setId(clone.getId());
		etree.setRoot(clone.getRoot());
		
		return etree;
	}
}
